package com.lzt.yijian.mvp.view.fragment;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleScanAndConnectCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.lzt.yijian.R;
import com.lzt.yijian.bean.Subjects;
import com.lzt.yijian.util.LztLog;
import com.lzt.yijian.util.NToast;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;


public class CollegeFragment extends Fragment {

    private static final int REQUEST_CODE_OPEN_GPS = 1;
    private static final int REQUEST_CODE_PERMISSION_LOCATION = 2;
    @BindView(R.id.college_bt_connect)
    Button mCollegeBtConnect;
    @BindView(R.id.college_bt_yanz)
    Button mCollegeBtYanz;

    private Context mContext;
    private List<Subjects> mSubjects = new ArrayList<>();

    Unbinder unbinder;
    @BindView(R.id.college_bt_scan)
    Button mCollegeBtScan;
    private String TAG = "myBle";
    private String mUuid_read;
    private String mUuid_service;
    private String mUuid_write;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View layout = inflater.inflate(R.layout.fragment_college, container, false);
        mContext = getContext();
        unbinder = ButterKnife.bind(this, layout);
        initView();
        return layout;
    }

    private void initView() {
        BleManager.getInstance().init(getActivity().getApplication());
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(1, 5000)
                .setConnectOverTime(20000)
                .setOperateTimeout(5000);
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @OnClick({R.id.college_bt_scan, R.id.college_bt_connect, R.id.college_bt_yanz})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.college_bt_scan:
                LztLog.i(TAG, "college_bt_scan");
                checkPermissions();
                break;
            case R.id.college_bt_connect:
                if (!list.isEmpty()) {
                    boolean connected = BleManager.getInstance().isConnected(list.get(0));
                    if (connected)
                        NToast.longToast("true");
                    else
                        NToast.longToast("false");
                } else {
                    NToast.longToast("list null");
                }
                break;
            case R.id.college_bt_yanz:
                LztLog.i(TAG, "##########################################################");
                byte[] bytes = {0x08, 0x04, 0x02, 0x00, 0x02, 0x00};
                writeByte(list.get(0), bytes);
                break;
        }
    }

    private void checkPermissions() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (!bluetoothAdapter.isEnabled()) {
            NToast.shortToast(R.string.please_open_blue);
            LztLog.i(TAG, "isEnabled");
            return;
        }

        String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
        List<String> permissionDeniedList = new ArrayList<>();
        for (String permission : permissions) {
            LztLog.i(TAG, "permissions");
            int permissionCheck = ContextCompat.checkSelfPermission(mContext, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission);
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            LztLog.i(TAG, "permissionDeniedList");
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            ActivityCompat.requestPermissions((Activity) mContext, deniedPermissions, REQUEST_CODE_PERMISSION_LOCATION);
        }
    }

    private void onPermissionGranted(String permission) {
        LztLog.i(TAG, "onPermissionGranted");
        switch (permission) {
            case Manifest.permission.ACCESS_FINE_LOCATION:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpen()) {
                    new AlertDialog.Builder(mContext)
                            .setTitle("提示")
                            .setMessage("当前手机扫描蓝牙需要打开定位功能")
                            .setNegativeButton("取消",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {

                                        }
                                    })
                            .setPositiveButton("前往设置",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                            startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                                        }
                                    })
                            .setCancelable(false)
                            .show();
                } else {
                    LztLog.i("bleDevice:--> ", "onPermissionGranted + else");
                    setScanRule();
                    startScan();
                }
                break;
        }
    }

    private void setScanRule() {
        String[] names = {"ESLinker"};
        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
                .setDeviceName(true, names)   // 只扫描指定广播名的设备，可选
                .setScanTimeOut(10000)              // 扫描超时时间，可选，默认10秒
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
    }

    List<BleDevice> list = new ArrayList<>();

    private void startScan() {
        BleManager.getInstance().scanAndConnect(new BleScanAndConnectCallback() {
            @Override
            public void onScanFinished(BleDevice scanResult) {
                Log.i(TAG, "onScanFinished: ");
                list.add(scanResult);
            }

            @Override
            public void onStartConnect() {
                Log.i(TAG, "onStartConnect: ");
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                Log.i(TAG, "onConnectFail: " + exception.getCode());
            }

            @Override
            public void onConnectSuccess(final BleDevice bleDevice, BluetoothGatt gatt, int status) {
                List<BluetoothGattService> services = gatt.getServices();
                BluetoothGattService service = services.get(3);
                mUuid_service = service.getUuid().toString();
                LztLog.i(TAG, "mUuid_service: --> " + mUuid_service);
                List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
                mUuid_read = characteristics.get(0).getUuid().toString();
                LztLog.i(TAG, "mUuid_read: --> " + mUuid_read);
                mUuid_write = characteristics.get(1).getUuid().toString();
                LztLog.i(TAG, "mUuid_write: --> " + mUuid_write);
                if (mUuid_service.isEmpty()) {
                    return;
                }
                if (mUuid_read.isEmpty()) {
                    return;
                }
                notifyByte(bleDevice);
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt
                    gatt, int status) {
                Log.i(TAG, "onDisConnected: ");
            }

            @Override
            public void onScanStarted(boolean success) {
                Log.i(TAG, "onScanStarted: ");
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                Log.i(TAG, "onScanning: ");
            }
        });
    }

    boolean flag = true;

    private void notifyByte(final BleDevice bleDevice) {
        BleManager.getInstance().notify(
                bleDevice,
                mUuid_service,
                mUuid_read,
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        LztLog.i(TAG, "onNotifySuccess:");
                        byte[] data = {0x08, 0x01, 0x04, 0x00};
                        writeByte(bleDevice, data);
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        LztLog.i(TAG, "onNotifyFailure:" + exception.getDescription());
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        // 打开通知后，设备发过来的数据将在这里出现
                        StringBuilder stringBuilder = new StringBuilder();
                        for (byte b : data) {
                            stringBuilder.append(String.valueOf(b));
                            stringBuilder.append(" ");
                        }
                        LztLog.i(TAG, "onCharacteristicChanged:byte --> " + stringBuilder.toString());
                    }
                });
    }

    //byte 与 int 的相互转换
    public byte intToByte(int x) {
        return (byte) x;
    }

    public int byteToInt(byte b) {
        //Java 总是把 byte 当做有符处理；我们可以通过将其和 0xFF 进行二进制与得到它的无符值
        return b & 0xFF;
    }

    private void writeByte(BleDevice bleDevice, byte[] data) {
        BleManager.getInstance().write(bleDevice, mUuid_service, mUuid_write, data,
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        int length = justWrite.length;
                        StringBuilder stringBuilder = new StringBuilder();
                        for (byte b : justWrite) {
                            stringBuilder.append(String.valueOf(b));
                            stringBuilder.append(" ");
                        }
                        LztLog.i(TAG, "onWriteSuccess:byte --> " + stringBuilder.toString());
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        LztLog.i(TAG, "onWriteFailure: " + exception.getDescription());
                    }
                }
        );
    }

    private void readByte(BleDevice bleDevice) {
        BleManager.getInstance().read(bleDevice, mUuid_service, mUuid_read, new BleReadCallback() {
            @Override
            public void onReadSuccess(byte[] data) {
                StringBuilder stringBuilder = new StringBuilder();
                if (data != null && data.length > 0) {
                    for (byte b : data) {
                        stringBuilder.append(String.valueOf(b));
                        stringBuilder.append(" ");
                    }
                }
                LztLog.i(TAG, "onReadSuccess:byte --> " + stringBuilder.toString());
            }

            @Override
            public void onReadFailure(BleException onReadFailure) {
                LztLog.i(TAG, "onReadFailure:byte --> " + onReadFailure.getDescription());
            }
        });
    }


    @Override
    public final void onRequestPermissionsResult(int requestCode,
                                                 @NonNull String[] permissions,
                                                 @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_PERMISSION_LOCATION:
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i]);
                        }
                    }
                }
                break;
        }
    }

    private boolean checkGPSIsOpen() {
        LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
        BleManager.getInstance().disconnectAllDevice();
        BleManager.getInstance().destroy();
    }

}
